package com.example.fast.service.impl;

import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import com.example.fast.common.exception.BaseErrorEnum;
import com.example.fast.common.exception.BaseException;
import com.example.fast.common.util.DTOUtils;
import com.example.fast.dao.JobDao;
import com.example.fast.dao.UserDao;
import com.example.fast.dao.UserJobDao;
import com.example.fast.domain.entity.JobEntity;
import com.example.fast.domain.entity.UserEntity;
import com.example.fast.domain.entity.UserJobEntity;
import com.example.fast.domain.enums.JobApplyStatusEnum;
import com.example.fast.domain.vo.JobAppliedVo;
import com.example.fast.domain.vo.JobApplyQuery;
import com.example.fast.domain.vo.JobApplyVo;
import com.example.fast.domain.vo.JobQuery;
import com.example.fast.domain.vo.JobUpdateVo;
import com.example.fast.domain.vo.JobVo;
import com.example.fast.service.JobService;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import static com.example.fast.domain.enums.JobStatusEnum.NOT_PASS;
import static com.example.fast.domain.enums.JobStatusEnum.PASS;
import static com.example.fast.domain.enums.JobStatusEnum.TODO;

/**
 * 岗位相关业务
 */
@Service
public class JobServiceImpl extends ServiceImpl<JobDao, JobEntity> implements JobService {

    @Autowired
    private UserJobDao userJobDao;
    @Autowired
    private UserDao userDao;

    @Override
    public List<JobVo> listJob(JobQuery jobQuery) {
        Map<String, Object> columnMap = new HashMap<>(2);
        if (jobQuery.getCreatorId() != null) {
            columnMap.put("creator_id", jobQuery.getCreatorId());
        }
        if (jobQuery.getStatus() != null) {
            columnMap.put("status", jobQuery.getStatus());
        }
        List<JobEntity> jobEntities = this.selectByMap(columnMap);

        Map<Long, UserEntity> userMap = new HashMap<>();

        return jobEntities.stream().map(jobEntity -> {
            JobVo jobVo = DTOUtils.map(jobEntity, JobVo.class);
            UserEntity userEntity = userMap.get(jobEntity.getCreatorId());
            if (userEntity == null) {
                userEntity = userDao.selectById(jobEntity.getCreatorId());
                userMap.put(jobEntity.getCreatorId(), userEntity);
            }
            jobVo.setCompanyName(userEntity != null ? userEntity.getCompanyName() : "-");
            jobVo.setCompanyDesc(userEntity != null ? userEntity.getCompanyDesc() : "-");

            UserJobEntity userJobEntity = userJobDao.selectByJobIdAndUserId(jobQuery.getApplicantId(), jobEntity.getId());
            jobVo.setCanApply(userJobEntity == null);
            return jobVo;
        }).collect(Collectors.toList());
    }

    @Override
    public void addJob(JobEntity jobEntity) {
        jobEntity.setId(null)
                 .setCreateTime(LocalDateTime.now())
                 .setUpdateTime(LocalDateTime.now())
                 .setStatus(TODO);
        this.insert(jobEntity);
    }

    @Override
    public void reviewJob(Long jobId, boolean result) {
        JobEntity jobEntity = this.selectById(jobId);
        if (jobEntity == null || jobEntity.getStatus() != TODO) {
            throw new BaseException(BaseErrorEnum.NULL_EXCEPTION, "岗位不存在或已审核");
        }
        JobEntity updateEntity = new JobEntity().setId(jobId)
                                                .setStatus(result ? PASS : NOT_PASS)
                                                .setUpdateTime(LocalDateTime.now());
        this.updateById(updateEntity);
    }

    @Override
    public void applyJob(JobApplyVo jobApplyVo) {
        JobEntity jobEntity = this.selectById(jobApplyVo.getJobId());
        if (jobEntity == null || jobEntity.getStatus() != PASS) {
            throw new BaseException(BaseErrorEnum.NULL_EXCEPTION, "岗位不存在");
        }

        List<UserJobEntity> userJobEntities = userJobDao.selectList(new EntityWrapper<UserJobEntity>()
                .eq("job_id", jobApplyVo.getJobId())
                .eq("user_id", jobApplyVo.getApplicantId())
        );
        if (CollectionUtils.isNotEmpty(userJobEntities)) {
            throw new BaseException(BaseErrorEnum.NULL_EXCEPTION, "不能重复申请");
        }

        UserJobEntity userJobAddEntity = new UserJobEntity()
                .setJobId(jobApplyVo.getJobId())
                .setUserId(jobApplyVo.getApplicantId())
                .setCostTime(0)
                .setApplyStatus(JobApplyStatusEnum.TODO)
                .setCreateTime(LocalDateTime.now())
                .setTestResult(jobApplyVo.getTestResult());
        userJobDao.insert(userJobAddEntity);
    }

    @Override
    public List<JobAppliedVo> listCandidateAppliedJob(JobApplyQuery jobApplyQuery) {
        List<UserJobEntity> userJobEntities = jobApplyQuery.getJobId() == null
                ? userJobDao.selectByUserId(jobApplyQuery.getApplicantId())
                : Collections.singletonList(userJobDao.selectByJobIdAndUserId(jobApplyQuery.getApplicantId(), jobApplyQuery.getJobId()));

        return DTOUtils.mapList(userJobEntities, JobAppliedVo.class).stream()
                       .peek(jobAppliedVo -> {
                           JobEntity jobEntity = this.baseMapper.selectById(jobAppliedVo.getJobId());
                           jobAppliedVo.setTitle(jobEntity.getTitle());
                           jobAppliedVo.setDescription(jobEntity.getDescription());
                           jobAppliedVo.setTestContent(jobEntity.getTestContent());

                           UserEntity userEntity = userDao.selectById(jobEntity.getCreatorId());
                           jobAppliedVo.setRecruiter(userEntity);
                       }).collect(Collectors.toList());
    }

    @Override
    public List<JobAppliedVo> listRecruiterJobApplied(JobApplyQuery jobApplyQuery) {
        Map<String, Object> map = new HashMap<>(2);
        map.put("creator_id", jobApplyQuery.getCreatorId());
        if (jobApplyQuery.getJobId() != null) {
            map.put("id", jobApplyQuery.getJobId());
        }
        List<JobEntity> jobEntities = this.selectByMap(map);
        if (CollectionUtils.isEmpty(jobEntities)) {
            return Collections.emptyList();
        }

        List<UserJobEntity> userJobEntities = userJobDao.selectList(
                new EntityWrapper<UserJobEntity>()
                        .in("job_id", jobEntities.stream().map(JobEntity::getId).collect(Collectors.toList()))
        );

        return DTOUtils.mapList(userJobEntities, JobAppliedVo.class).stream()
                       .peek(jobAppliedVo -> {
                           JobEntity jobEntity = this.baseMapper.selectById(jobAppliedVo.getJobId());
                           jobAppliedVo.setTitle(jobEntity.getTitle());
                           jobAppliedVo.setDescription(jobEntity.getDescription());
                           jobAppliedVo.setTestContent(jobEntity.getTestContent());

                           jobAppliedVo.setCandidate(userDao.selectById(jobAppliedVo.getUserId()));
                       }).collect(Collectors.toList());
    }

    @Override
    public void reviewMyJob(JobApplyQuery jobApplyQuery) {
        UserJobEntity userJobEntity = userJobDao.selectByJobIdAndUserId(jobApplyQuery.getApplicantId(), jobApplyQuery.getJobId());
        if (userJobEntity == null) {
            throw new BaseException(BaseErrorEnum.NULL_EXCEPTION, "申请记录不存在");
        }

        userJobEntity.setApplyStatus(jobApplyQuery.getResult() ? JobApplyStatusEnum.PASS : JobApplyStatusEnum.NOT_PASS)
                     .setUpdateTime(LocalDateTime.now());
        userJobDao.updateById(userJobEntity);
    }

    @Override
    public void delJob(Long jobId) {
        userJobDao.delete(
                new EntityWrapper<UserJobEntity>()
                        .eq("job_id", jobId)
        );
        this.deleteById(jobId);
    }

    @Override
    public void updateJob(JobUpdateVo jobUpdateVo) {
        JobEntity jobEntity = this.selectById(jobUpdateVo.getJobId());
        if (jobEntity == null) {
            throw new BaseException(BaseErrorEnum.NULL_EXCEPTION, "岗位不存在");
        }
        jobEntity.setTitle(jobUpdateVo.getTitle())
                 .setDescription(jobUpdateVo.getDescription())
                 .setTestContent(jobUpdateVo.getTestContent())
                 .setUpdateTime(LocalDateTime.now());
        this.updateById(jobEntity);
    }
}